/*
 * 人人信用管理有限公司版权所有.
 * 
 * @Description:
 * 
 * @author: liyuliang
 * 
 * @date: 20 Apr 2017 10:44:16 am
 * 
 * 注意：本内容仅限于人人信用管理有限公司内部传阅，禁止外泄以及用于其他的商业目的.
 */

package com.rrx360.common.web.filter;

import java.io.IOException;

import javax.annotation.PostConstruct;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.web.filter.GenericFilterBean;

import com.rrx360.common.config.ConfigChangeEvent;
import com.rrx360.common.config.ConfigChangeListener;
import com.rrx360.common.config.global.GlobalConfig;
import com.rrx360.common.context.ActionContext;
import com.rrx360.common.context.ActionContextKey;
import com.rrx360.common.web.matcher.ServletPathMatcher;
import com.rrx360.common.web.util.HsrUtil;

public class RequestProcessFilter extends GenericFilterBean {

  public static final Logger logger = LogManager.getLogger(RequestProcessFilter.class);

  private String alertPerfKey = "requestProcessor.alertPerf";

  private String alertPerfThresholdKey = "requestProcessor.alertPerfThreshold";

  private boolean alertPerf = false;

  private int alertPerfThreshold = 20000;

  private ServletPathMatcher noAlertPathMatcher;

  private ServletPathMatcher noCachePathMatcher;

  public ServletPathMatcher getNoCachePathMatcher() {
    return noCachePathMatcher;
  }

  public void setNoCachePathMatcher(ServletPathMatcher noCachePathMatcher) {
    this.noCachePathMatcher = noCachePathMatcher;
  }

  @PostConstruct
  public void init() {
    GlobalConfig.addConfigChangeListener(alertPerfKey, (event) -> {
      this.alertPerf = Boolean.valueOf(event.getNewValue());
    });
    GlobalConfig.addConfigChangeListener(alertPerfThresholdKey, (event) -> {
      this.alertPerfThreshold = Integer.parseInt(GlobalConfig.get(alertPerfThresholdKey, "20000"));
    });
  }

  @Override
  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException {
    HttpServletRequest hsr = (HttpServletRequest) request;
    long startTime = System.currentTimeMillis();
    // System.out.println(request.getServerPort());
    // Enumeration<String> en = hsr.getHeaderNames();
    // if(en != null) {
    // while(en.hasMoreElements()) {
    // String name = en.nextElement();
    // System.out.println(name + " " + hsr.getHeader(name));
    // }
    // }
    if (noCachePathMatcher != null && noCachePathMatcher.match(hsr)) {
      HttpServletResponse res = (HttpServletResponse) response;
      res.setHeader("Pragma", "no-cache");
      res.setDateHeader("Expires", 0);
      res.addHeader("Cache-Control", "no-cache");// 浏览器和缓存服务器都不应该缓存页面信息
      res.addHeader("Cache-Control", "no-store");// 请求和响应的信息都不应该被存储在对方的磁盘系统中；
      res.addHeader("Cache-Control", "must-revalidate");
    }
    ActionContext.clear();
    ActionContext.put(ActionContextKey.HTTP_SERVLET_REQUEST, request);
    ActionContext.put(ActionContextKey.HTTP_SERVLET_RESPONSE, response);
    try {
      chain.doFilter(request, response);
    } finally {
      long elapsedTime = System.currentTimeMillis() - startTime;
      logger.info("request Url:" + hsr.getServletPath() + " " + HsrUtil.getClientIp(hsr) + " "
          + elapsedTime);
//      if (alertPerf && elapsedTime > alertPerfThreshold
//          && (noAlertPathMatcher == null || !noAlertPathMatcher.match(hsr))) {
////        AlertUtil.alert(ExceptionType.REQUEST_PROCESS_SLOW,
//            "请求处理慢;地址:" + hsr.getServletPath() + " 时间:" + elapsedTime);
//      }

    }
  }



  @Override
  public void destroy() {

  }

  public boolean isAlertPerf() {
    return alertPerf;
  }

  public void setAlertPerf(boolean alertPerf) {
    this.alertPerf = alertPerf;
  }

  public int getAlertPerfThreshold() {
    return alertPerfThreshold;
  }

  public void setAlertPerfThreshold(int alertPerfThreshold) {
    this.alertPerfThreshold = alertPerfThreshold;
  }

  public ServletPathMatcher getNoAlertPathMatcher() {
    return noAlertPathMatcher;
  }

  public void setNoAlertPathMatcher(ServletPathMatcher noAlertPathMatcher) {
    this.noAlertPathMatcher = noAlertPathMatcher;
  }


}
